using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;

namespace UCL.Powersource.Statistics
{
    /// <summary>
    /// Statistics utilities class
    /// </summary>
    public static class StatisticsUtilities
    {
       
        private static ILog Log = LogManager.GetLog(typeof(WIStateStatisticsBase));

        /// <summary>
        /// Get the current date of the work item
        /// </summary>
        /// <param name="timeframe">Work item time frame</param>
        /// <returns>The work item date</returns>
        public static DateTime GetAsOfDate(ITimeFrameIteration timeframe)
        {
            DateTime dt = (DateTime)timeframe.FinishDate;

            return new DateTime(dt.Year, dt.Month, dt.Day, 23, 59, 59);
        }

        /// <summary>
        /// Get the work item store
        /// </summary>
        /// <param name="teamProjConfig">Tfs stat project configuration</param>
        /// <returns>The collection of work item store</returns>
        public static WorkItemStore GetWIStore(ITfsTeamProjectConfiguration teamProjConfig)
        {
            var collection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(teamProjConfig.TeamProjectCollectionConfiguration.Uri));

            return collection.GetService<WorkItemStore>();
        }

        
        public static string Format(List<int> temp)
        {
            if (temp.Count == 0) return "''";

            return String.Join(", ", temp.ToArray());
        }

        /// <summary>
        /// Get the product backlog items
        /// </summary>
        /// <param name="wiStore">Work item store</param>
        /// <param name="variables">Variables</param>
        /// <param name="retrieveOnlyRootElements">Retrieve only root elements</param>
        /// <returns></returns>
        public static WorkItemCollection GetPBIs(WorkItemStore wiStore, Dictionary<string, Object> variables, bool retrieveOnlyRootElements)
        {
            WorkItemLinkInfo[] queryLinkResults = null;
            string state;
            if (variables.ContainsKey("State")) state = "<> 'Removed'";
            else state = "= 'Done'";

            string qString = "SELECT [Id] " +
                "FROM WorkItemLinks " +
                "WHERE ([Source].[System.WorkItemType] = 'Product Backlog Item'  " +
                "AND  [Source].[State] <> 'Removed') " +
                "And ([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward') " +
                "And ([Target].[System.WorkItemType] = 'Task'  " +
                "AND  [Target].[State] " + state + " AND [Target].[Iteration Path] Under @IterationPath) " +
                "AsOf @AsOf";
            
            Query query;

            try
            {
                query = new Query(wiStore, qString, variables);
                queryLinkResults = query.RunLinkQuery();
            }
            catch (ValidationException exc)
            {
                Log.Error(exc, "Invalid argument in query string in GetPBIs() method.");
            }

            List<int> temp = new List<int>();
            string str;

            if (queryLinkResults != null)
            {
                foreach (WorkItemLinkInfo link in queryLinkResults)
                {
                    if (link.SourceId != 0 && retrieveOnlyRootElements) continue;

                    temp.Add(link.TargetId);
                }
            }

            WorkItemCollection results = null;
            str = StatisticsUtilities.Format(temp);

            qString = "Select [ID], [Iteration Path], [State] From WorkItem Where [ID] IN (" + str + ") AsOf @AsOf";

            try
            {
                query = new Query(wiStore, qString, variables);
                results = query.RunQuery();
            }
            catch (ValidationException exc)
            {
                Log.Error(exc, "Invalid argument in query string in GetPBIs() method.");
            }

            return results;
        }

        /// <summary>
        /// Class for valid iteration path
        /// </summary>
        /// <param name="teamProjConfig">Tfs stat project configuration</param>
        /// <param name="timeFrame">Iteration time frame</param>
        /// <returns></returns>
        public static bool ValidIterationPath(ITfsTeamProjectConfiguration teamProjConfig, ITimeFrame timeFrame)
        {
            var wiStore = StatisticsUtilities.GetWIStore(teamProjConfig);

            ITimeFrameIteration iterationTimeFrame = (ITimeFrameIteration)timeFrame;

            Dictionary<string, Object> variables = new Dictionary<string, Object>();
            variables.Add("IterationPath", iterationTimeFrame.GetIterationPathForProject(teamProjConfig));

            string qString = "Select [ID] From WorkItems Where [Iteration Path] Under @IterationPath";

            try
            {
                Query query = new Query(wiStore, qString, variables);
            }
            catch (ValidationException exc)
            {
                Log.Error(exc, "TimeFrameIteration IterationPath is not valid, no such iteration path for {0} Project.", teamProjConfig.UniqueName, iterationTimeFrame.IterationPath);
                return false;
            }
            return true;
        }
    }
}
